//Dart语言

//dart 基础
//1. 变量
void fun1() {
  //1. var 可以接收任何类型的变量,
  // 变量⼀旦赋值，类型便会确定，则不能再改变其类型
  var t;
  t = "hello world";
  t = 100;
  //2.Dynamic  和 Object  与  var  功能相似，都会在赋值时⾃动进⾏类型推断
  //不同在于，赋值后可以改变其类型
  //object  是dart所有对象的根基类,所以任何类型的数据都可以赋值给 Object  声明的对象，
  // 所以表现效果和 dynamic  相似
  dynamic d;
  d = "ddddd";
  d = 1000;
  //3. final和const:  const  变量是⼀个编译时常量， final  变量在第⼀次使⽤时被初始化
  //被 final  或者 const  修饰的变量，变量类型可以省略
  //final属于单赋值，使用final修饰的变量必须进行初始化，一旦被赋值以后，不能被再次赋值。
  //const修饰的变量它会在编译器以至于应用整个生命周期内都是不可变的常量，在内存中也只会创建一次，之后的每次调用都会复用第一次创建的对象。
  //可以省略String这个类型声明
  // final String str = "hi world";
  final str = "hello";
  const str1 = "world";
}

//2. 函数: Dart是⼀种真正的⾯向对象的语⾔，所以即使是函数也是对象，并且有
// ⼀个类型Function。这意味着函数可以赋值给变量或作为参数传递给其他函数，
// 这是函数式编程的典型特征。

var _nobleGases = ['a', 'b', 'c'];
var maps = {1: "11"};
//2.1 函数声明
bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

//不指定返回类型，此时默认为dynamic，不是bool
//isNoble1(int atomicNumber){
//  return _nobleGases[atomicNumber]!=null;
//}

typedef bool CALLBACK();

void test(CALLBACK cb) {
  print(cb());
}

//2.2 对于只包含⼀个表达式的函数，可以使⽤简写语法
bool isNoble2(int atomicNumber) => _nobleGases[atomicNumber] != null;

//2.3 函数作为变量
var say = (str) {
  print(str);
};

//2.4 函数作为参数传递
void execute(var callback) {
  callback();
}

//2.5 可选的位置参数
//包装⼀组函数参数，⽤[]标记为可选的位置参数：
String say1(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = "$result with a $device";
  }
  return result;
}

//2.6 可选的命名参数
void enableFlags({bool bold, bool hidden}) {}

void fun2() {
  test(() => true);
  say("abc");
  execute(() => print("abc"));
  say1('bob', "hello");
  say1('Bob', 'Howdy', 'smoke signal');
  enableFlags(hidden: true);
  enableFlags(bold: false, hidden: true);
  enableFlags(hidden: true, bold: false);
}

//3. 异步支持:
//Dart类库有⾮常多的返回 Future  或者 Stream  对象的函数。 这些函数被称为异步函数：
// 它们只会在设置好⼀些耗时操作之后返回，⽐如像 IO操作。⽽不是等到这个操作完成。
//async  和 await  关键词⽀持了异步编程，运⾏您写出和同步代码很像的异步代码
//3.1 Future ( 相当于JavaScript的 Promise)
//Future  与JavaScript中的 Promise  ⾮常相似，表示⼀个异步操作的最终完成（或失败）及其结果值的表示。简单来
//说，它就是⽤于处理异步操作的，异步处理成功了就执⾏成功的操作，异步处理失败了就捕获错误或者停⽌后续操作。
//⼀个Future只会对应⼀个结果，要么成功，要么失败。
void fun3() {
  //Future.then
  Future.delayed(new Duration(seconds: 2), () {
    return 'hello';
  }).then((data) {
    print(data);
  });
  //Future.catchError
  Future.delayed(new Duration(seconds: 2), () {
    throw AssertionError("error");
  }).then((data) {
    print("sucess");
  }).catchError((e) {
    print(e);
  });
  //then  ⽅法还有⼀个可选参数 onError
  Future.delayed(new Duration(seconds: 2), () {
    throw AssertionError("error");
  }).then((data) {
    print("success");
  }, onError: (e) {
    print(e);
  });
  //Future.whenComplete
  //有些时候，我们会遇到⽆论异步任务执⾏成功或失败都需要做⼀些事的场景
  Future.delayed(new Duration(seconds: 2), () {
    throw AssertionError("error");
  }).then((data) {
    print(data);
  }).catchError((e) {
    print(e);
  }).whenComplete(() {
    print("complete");
  });
  //Future.wait
  //有些时候，我们需要等待多个异步任务都执⾏结束后才进⾏⼀些操作
  Future.wait([
    Future.delayed(new Duration(seconds: 2), () {
      return 'hello';
    }),
    Future.delayed(new Duration(seconds: 2), () {
      return "world";
    })
  ]).then((results) {
    print(results[0] + results[1]);
  }).catchError((e) {
    print(e);
  });

  //Async/await
  Future<String> login(String userName, String pwd) {
    //用户登录获取id
  }
  Future<String> getUserInfo(String id) {
    //由id获取用户信息
  }
  Future saveUserInfo(String userInfo) {
    //保存用户信息
  }
  //回调地狱(Callback hell)
  login("user", "666").then((id) {
    getUserInfo(id).then((userInfo) {
      saveUserInfo(userInfo);
    });
  });
  //使用Future消除callback hell
  login("user2", "888").then((id) {
    return getUserInfo(id);
  }).then((userInfo) {
    return saveUserInfo(userInfo);
  }).then((e) {
    //do something
  }).catchError((e) {
    print(e);
  });
  //使用async/await消除callback hell
  //async  ⽤来表示函数是异步的，定义的函数会返回⼀个 Future  对象，
  // 可以使⽤then⽅法添加回调函数
  //await  后⾯是⼀个 Future  ，表示等待该异步任务完成，异步完成后才会往下⾛；
  // await  必须出现在  async  函数内部
  task() async {
    try {
      String id = await login("user3", "999");
      String userInfo = await getUserInfo(id);
      await saveUserInfo(userInfo);
    } catch (e) {
      print(e);
    }
  }
  task();
  //stream
  //也是⽤于接收异步事件数据，和 Future  不同的是，它可以接收多个异步操作的结果（成功或失败）。 也就是
  //说，在执⾏异步任务时，可以通过多次触发成功或失败事件来传递结果数据或错误异常。  Stream  常⽤于会多次读取数
  //据的异步任务场景，如⽹络内容下载、⽂件读写等
  Stream.fromFutures([
    Future.delayed(new Duration(seconds: 1),(){
      return "hello 1";
    }),
    Future.delayed(new Duration(seconds: 1),(){
      throw AssertionError('error');
    }),
    Future.delayed(new Duration(seconds: 1),(){
      return "hello 3";
    })
  ]).listen((data){
    print(data);
  },onError: (e){
    print(e);
  },onDone: (){});
}
